package com.qkjia.buffer;

import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class BufferDemo2 {

    static private final int start = 0;
    static private final int size = 1024;

    // 内存映射文件io
     @Test
     public void b04() throws Exception {
         RandomAccessFile raf = new RandomAccessFile("e:\\qkjia\\01.txt", "rw");
         FileChannel fc = raf.getChannel();
         // 将此通道文件的一个区域直接映射到内存中  FileChannel.MapMode.READ_WRITE 读/写映射模式
         MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, start, size);

         mbb.put(0, (byte) 97);
         mbb.put(1023, (byte) 122);
         raf.close();
     }
    // 直接缓冲区
    @Test
    public void b03() throws Exception {
        String infile = "e:\\qkjia\\01.txt";
        FileInputStream fin = new FileInputStream(infile);
        FileChannel finChannel = fin.getChannel();

        String outfile = "e:\\qkjia\\02.txt";
        FileOutputStream fout = new FileOutputStream(outfile);
        FileChannel foutChannel = fout.getChannel();

        //创建直接缓冲区  ByteBuffer.allocateDirect(1024); 分配一个新的直接字节缓冲区
        ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

        while (true) {
            buffer.clear();
            int r = finChannel.read(buffer);
            if(r == -1) {
                break;
            }
            // 翻转这个缓冲区。 将限制设置为当前位置，然后将位置设置为零
            buffer.flip();
            foutChannel.write(buffer);
        }
    }

    //只读缓冲区
    @Test
    public void b02() {
         // ByteBuffer.allocate(10); 分配一个新的字节缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(10);

        // buffer.capacity() 返回此缓冲区的容量。
        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte)i);
        }

        //创建只读缓冲区
        ByteBuffer readonly = buffer.asReadOnlyBuffer();

        // buffer.capacity() 容量
        for (int i = 0; i < buffer.capacity(); i++) {
            byte b = buffer.get(i);
            b *=10;
            // 绝对放置方法（可选操作）
            buffer.put(i,b);
        }

        // readonly.position(0); 设置此缓冲区的位置。 如果标记已定义且大于新位置，则将其丢弃
        readonly.position(0);
        // 设置此缓冲区的限制
        readonly.limit(buffer.capacity());

        // readonly.remaining()>0 位置和限制之间的元素数。
        while (readonly.remaining()>0) {
            System.out.println(readonly.get());
        }
    }


    //缓冲区分片
    @Test
    public void b01() {
         // ByteBuffer.allocate(10); 分配一个新的字节缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(10);

        // buffer.capacity(); 返回此缓冲区的容量。
        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte)i);
        }

        // 创建子缓冲区
        //  buffer.position(3); 设置此缓冲区的位置。 如果标记已定义且大于新位置，则将其丢弃
        buffer.position(3);
        // buffer.limit(7); 设置此缓冲区的限制。 如果头寸大于新限制，则将其设置为新限制
        buffer.limit(7);
        // buffer.slice(); 创建一个新的字节缓冲区，其内容是此缓冲区内容的共享子序列。
        ByteBuffer slice = buffer.slice();

        // 改变子缓冲区内容
        for (int i = 0; i <slice.capacity() ; i++) {
            byte b = slice.get(i);
            b *=10;
            slice.put(i,b);
        }

        // 设置此缓冲区的位置
        buffer.position(0);
        buffer.limit(buffer.capacity());

        while(buffer.remaining()>0) {
            System.out.println(buffer.get());
        }
    }
}
